package cn.edu.szu;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Base64;

public class RSAUtils {
    // 公钥和私钥
    private BigInteger n, e, d;

    // 创建RSA加密器
    public RSAUtils(KeyGeneration keyGeneration) {
        // 初始化密钥
        n = keyGeneration.getN();
        e = keyGeneration.getE();
        d = keyGeneration.getD();

    }

    // 加密文件
    public File encrypt (File origin) {
        // 处理后的文件
        File done = new File("E_" + origin.getName());

        // 明文，一次读取1000bit
        byte []plainTex = new byte[125];

        // 每次加密完均为1024bit的字节数组，这样解密的时候就能够实现
        try {
            // 定义输入和输出流，用以读取原文件和写入加密文件
            FileInputStream input = new FileInputStream(origin);
            FileOutputStream out = new FileOutputStream(done);
            while (input.read(plainTex) != -1) {
                out.write(encrypt(plainTex));
                out.flush();
            }
        } catch (IOException e) {
        }

        return done;
    }

    // 解密文件
    public void decrypt (File origin) {
        // 处理后的文件
        File done = new File("D_" + origin.getName().substring(2));

        // 密文，一次读取1024bit
        byte []cipherText = new byte[128];

        // 每次加密完均为1024bit的字节数组，这样解密的时候就能够实现
        try {
            // 定义输入和输出流，用以读取原文件和写入加密文件
            FileInputStream input = new FileInputStream(origin);
            FileOutputStream out = new FileOutputStream(done);
            while (input.read(cipherText) != -1) {
                System.out.println(decrypt(cipherText));
                out.write(decrypt(cipherText));
                out.flush();
            }
        } catch (IOException e) {
        }
    }

    // 加密明文字节数组
    public byte[] encrypt (byte[] message) {

        // 直接将读取到的字节数组转换成BigInteger
        BigInteger plainText = new BigInteger(1, message);

        // 按照加密公式进行加密
        BigInteger cipherText = plainText.modPow(e, n);

        // 返回加密后的字节数组
        return cipherText.toByteArray();
    }

    // 解密密文字节数组
    private byte[] decrypt (byte[] message) {

        // 直接将读取到的字节数组转换成BigInteger
        BigInteger cipherText = new BigInteger(1, message);

        // 按照解密公式进行加密
        BigInteger plainText = cipherText.modPow(d, n);

        // 待处理的字节数组
        byte []data = plainText.toByteArray();

        // 返回完整的字节
        return IntegerUtils.clearBits(data);
    }

    // 加密明文String
    public String encrypt (String message) {

        // 按照加密公式进行加密
        byte[] cipherText = encrypt(message.getBytes());

        // 将密文字节按照Base64编码
        return Base64.getEncoder().encodeToString(cipherText);
    }

    // 解密密文String
    public String decrypt (String message) {

        // 将Base64编码的字符串解码成字节数组
        byte[] cipherText = Base64.getDecoder().decode(message);

        // 返回解密后的字符串
        return new String(decrypt(cipherText));
    }
}
